﻿// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BootstrapBlazor.Components;

/// <summary>
/// <see cref="NavbarDropdown"/> 组件的容器，可包含一个或多个 <see cref="NavbarDropdownItem"/>。
/// </summary>
public sealed partial class NavbarDropdownMenu : IDisposable
{
    /// <summary>
    /// 获得 样式类集合 
    /// </summary>
    /// <returns></returns>
    private string? DropdownClassString => CssBuilder.Default()
        .AddClass("dropdown-menu navbar-h-dropdown-menu", ParentDropdownState.IsHorizontal)
        .AddClass("navbar-v-dropdown-menu", !ParentDropdownState.IsHorizontal)
        .AddClass("show", ParentDropdownState.DropdownVisible)
        .AddClass("navbar-v-right", !ParentDropdownState.IsHorizontal && ParentDropdownState.IsRTL)
        .AddClass("dropdown-menu-end", ParentDropdownState.IsHorizontal && ParentDropdownState.IsRTL)
        .AddClassFromAttributes(AdditionalAttributes)
        .Build();

    /// <summary>
    /// 获得 样式类集合 
    /// </summary>
    /// <returns></returns>
    private string? DropdownContainerClassString => CssBuilder.Default()
        .AddClass("navbar-v-dropdown-menu-container")
        .AddClass("navbar-v-right", !ParentDropdownState.IsHorizontal && ParentDropdownState.IsRTL)
        .AddClass("dropdown-menu-end", ParentDropdownState.IsHorizontal && ParentDropdownState.IsRTL)
        .AddClass("d-none", !ParentDropdownState.IsMixinDisplay && !ParentDropdownState.IsPopoutDisplay)
        .AddClassFromAttributes(AdditionalAttributes)
        .Build();

    /// <summary>
    /// 获得 样式类集合 
    /// </summary>
    /// <returns></returns>
    private string? FloatingClassString => CssBuilder.Default("navbar-v-dropdown-menu")
        .AddClass("show", ParentDropdownState.DropdownVisible)
        .AddClass("navbar-v-right", ParentDropdownState.IsRTL)
        .AddClassFromAttributes(AdditionalAttributes)
        .Build();

    /// <summary>
    /// 获得 样式类集合 
    /// </summary>
    /// <returns></returns>
    private string? FloatingContainerClassString => CssBuilder.Default()
        .AddClass("navbar-v-dropdown-menu-container")
        .AddClass("navbar-v-right", ParentDropdownState.IsRTL)
        .AddClass("navbar-v-floating", !ParentDropdownState.IsMixinDisplay)
        .AddClass("d-none", ParentDropdownState.IsMixinDisplay)
        .AddClassFromAttributes(AdditionalAttributes)
        .Build();

    private ElementWrapper Wrapper { get; set; } = new();

    private JSInterop<NavbarDropdownMenu>? Interop { get; set; }

    /// <summary>
    /// 获得/设置 父级 <see cref="NavbarDropdown"/> 组件的状态
    /// </summary>
    [CascadingParameter]
    public NavbarDropdownState ParentDropdownState { get; set; } = new();

    /// <summary>
    /// 获得/设置 父级 <see cref="NavbarDropdown"/> 组件的引用
    /// </summary>
    [CascadingParameter]
    public NavbarDropdown? ParentDropdown { get; set; }

    /// <summary>
    /// 放置此 <see cref="NavbarDropdown"/> 的 <see cref="NavbarItem"/> 组件。
    /// </summary>
    [CascadingParameter]
    public NavbarItem? ParentItem { get; set; }

    /// <summary>
    /// 获得/设置 父级 <see cref="NavbarItem"/> 组件的状态
    /// </summary>
    [CascadingParameter]
    public NavbarItemState ParentItemState { get; set; } = new();

    /// <summary>
    /// 获得/设置 子组件内容
    /// </summary>
    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    /// <summary>
    /// OnAfterRenderAsync
    /// </summary>
    /// <param name="firstRender"></param>
    /// <returns></returns>
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (firstRender)
        {
            if (Interop is null)
            {
                Interop = new JSInterop<NavbarDropdownMenu>(JSRuntime);
            }
            await Interop.InvokeVoidAsync(this, Wrapper.Ref, "bb_leave_navbar_dropdown_menu");
        }
        else
        {
            //执行延迟的方法
            if (ParentDropdown?.ExecuteAfterRenderQueue?.Count > 0)
            {
                while (ParentDropdown.ExecuteAfterRenderQueue.Count > 0)
                {
                    await ParentDropdown.ExecuteAfterRenderQueue.Dequeue()();
                }
            }
        }
    }

    /// <summary>
    /// 鼠标移入处理事件
    /// </summary>
    /// <returns></returns>
    public async Task OnMouseEnterHandler()
    {
        if (ParentDropdown is not null)
        {
            ParentDropdownState.HoverMenu = true;

            if (!ParentDropdownState.DropdownVisible)
            {
                await ParentDropdown.OnMouseEnterHandler();
            }
        }
    }

    /// <summary>
    /// 鼠标移出处理事件
    /// </summary>
    /// <returns></returns>
    public async Task OnMouseLeaveHandler()
    {
        if (ParentDropdown is not null)
        {
            ParentDropdownState.HoverMenu = false;

            await ParentDropdown.OnMouseLeaveHandler();
        }
    }

    /// <summary>
    /// 鼠标移出浮动菜单处理
    /// </summary>
    /// <returns></returns>
    [JSInvokable]
    public async Task FloatingLeaveHandler()
    {
        if (ParentDropdown is not null)
        {
            ParentDropdownState.HoverMenu = false;

            if (ParentDropdown.HasHovered)
            {
                return;
            }

            if (ParentDropdown.HasSubmenu)
            {
                if (ParentDropdown.ChildDropdowns.Any(x => x.Visible))
                {
                    return;
                }
            }

            await ParentDropdown.OnMouseLeaveHandler();

            //向上关闭所有
            if (ParentDropdown.IsDropdownSubmenu)
            {
                var dropdown = ParentDropdown;
                while (dropdown.ParentDropdown is not null)
                {
                    dropdown = dropdown.ParentDropdown;
                    if (dropdown.ChildDropdowns.Any(x => x.HasHovered))
                    {
                        break;
                    }
                    await dropdown.OnMouseLeaveHandler();
                }
            }
        }
    }

    /// <summary>
    /// Dispose
    /// </summary>
    /// <param name="disposing"></param>
    private void DisposeCore(bool disposing)
    {
        if (disposing)
        {
            Interop?.Dispose();
        }
    }

    /// <summary>
    /// Dispose 方法
    /// </summary>
    public void Dispose()
    {
        DisposeCore(true);
        GC.SuppressFinalize(this);
    }
}
